
//#define BOOST_FILESYSTEM_NO_DEPRECATED
#define GL3_PROTOTYPES
#include <iostream>
#include <GL/glew.h>

#include "SDL/SDL.h"
#include "Environment.h"
#include "Matrix4.h"
#include "MatrixHelpers.h"
//#include "DisplayObject.h"


namespace Krengine
{
	Environment::Environment( int windowWidth, int windowHeight, bool _3D )
		: width(windowWidth),
		  height(windowHeight),
		  window(0),
		  running(false),
		  renderbitFlags(0),
		  projectionMatrix()
	{
		/* initialize SDL video mode */
        SDL_Init(SDL_INIT_VIDEO);
        /* create screen in windowed mode */
        window = SDL_SetVideoMode(GLint(width), GLint(height), 0, SDL_OPENGL | SDL_GL_DOUBLEBUFFER);

		if( glewInit() != GLEW_OK )
			throw "Error initializing GLEW";

		/* set clearcolor to dark grey */
        glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
		
		if (_3D)
		{
			/* enable depth test */
			glEnable(GL_DEPTH_TEST);
			/* create 3D perspective view */
			projectionMatrix = perspectiveMatrix( 45.0f, (float)width/height, 0.1f, 500.0f );
			/* register render properties */
			renderbitFlags = GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT;
		} else
		{
			/* register render properties */
			renderbitFlags = GL_COLOR_BUFFER_BIT;
		}
		
		/* engine is setup and running */
		running = true;
	}

	Environment::~Environment()
	{
		if ( window != 0 )
			SDL_FreeSurface(window);
	}


	void Environment::attachObject( DisplayObject& dispObj )
	{
		dispObj.prepareForRender(&projectionMatrix);
		displayList.push_back(&dispObj);
	}


	/**
	 * Renders one frame
	 */
	void Environment::render( void (*_update)() )
	{
		//TODO FIXME
		std::cout << "rendering...\n";

		while ( running )
		{
			//if ( Timer::instance()->prevFrame < Timer::instance()->getFrameNum() )
			//{
				/* Clear the screen */
				glClear(renderbitFlags);

				/* process SDL events */
				catchSDLEvents();

				/* update scene */
				_update();

				for ( unsigned int i = 0; i < displayList.size(); i++ )
					displayList[i]->render();

				/* update screen */
				SDL_GL_SwapBuffers();
			//}
		}
	}


	void Environment::catchSDLEvents()
	{
		SDL_Event event;
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_ACTIVEEVENT:
					/* check if app is activated or iconified */
					if ( event.active.state & SDL_APPACTIVE )
					{
						if ( event.active.gain )
							std::cout << "Application activated" << std::endl;
						else
							std::cout << "Application iconified" << std::endl;
					}
					break;
				case SDL_MOUSEBUTTONDOWN:
				case SDL_MOUSEBUTTONUP:
				//case SDL_MOUSEMOTION:
					std::cout << "mouse button pressed!" << std::endl;
					//handleMouseEvents(&event);
					break;
				case SDL_KEYDOWN:
				case SDL_KEYUP:
					std::cout << "key pressed!" << std::endl;
					//handleKeyEvents(&event.key.keysym, false);
					break;
				case SDL_QUIT:
					exitProgram(0);
					break;
			}
		}
	}


	/**
	 * stops rendering and cleans up resources
	 */
	void Environment::exitProgram( int code )
	{
		/* Krengine is stopping */
		running = false;

		std::cout << "freeing SDL surface" << std::endl;
		/* free resources allocated for SDL Surface */
		SDL_FreeSurface(window);

		std::cout << "shutting down!" << std::endl;
		
		/* shutdown program */
		SDL_Quit();
		exit( code );
	}
}